import boqdoc
import fileio
from cmdbase import *
from cmdobjects import Event, event

from stdwidgets import Msg
from PyQt4.QtCore import *

class DocManager(object):
   '''Manages the boq document.'''

   __instance = None

   def __new__(cls):
      '''Implements a singleton pattern.'''
      if cls.__instance is None:
         self = cls.__instance = object.__new__(cls)
         self.doc = None
         self.filename = None
         self.undostack = UndoStack()

         self.evt_opened = Event()
         self.evt_closed = ~self.evt_opened

      return cls.__instance

   # Query status

   @property
   def isopen(self):
      '''Checks if a document is open.'''
      return self.doc is not None

   @property
   def modified(self):
      return not self.undostack.isClean()

   def setclean(self):
      self.undostack.setClean()

   @property
   def availColumns(self):
      return filter(
         lambda cls: hasattr(cls, '__bases__') and boqdoc.Column in cls.__bases__,
         boqdoc.__dict__.values())

   # Dialog functions

   def _querysave(self):
      return QMessageBox.warning(None, 'Close',
         "The document has been modified.\nDo you want to save your changes?",
         QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save)

   def _querysavename(self):
      return QFileDialog.getSaveFileName(None, 'Save As', QDir.home().absolutePath(), 'Documents (*.soq)')

   def _queryopenname(self):
      return QFileDialog.getOpenFileName(None, 'Open', QDir.home().absolutePath(), 'Documents (*.soq)')


   # Actions

   def new(self):
      '''Create a new document.'''
      if self.isopen:
         self.close()
      self.doc = boqdoc.Doc()
      #self.doc.schedules.columns.append(name='Name', interface=boqdoc.PropertyInterface(property='name'))
      self.evt_opened()

   def close(self):
      '''Closes the currently open document.
      Returns False the file remains open (i.e. isopen() is True).'''
      if not self.isopen:
         return True
      elif self.modified:
         save = self._querysave()
         if save == QMessageBox.Cancel:
            return False
         elif save == QMessageBox.Save:
            self.save()
      self.undostack.clear()
      self.doc.clear()
      self.doc = None
      self.filename = None
      self.evt_closed()
      return True


   def save(self):
      '''Save the open document.'''
      if self.filename in (None, ''):
         return self.saveas()
      else:
         return self._savetofilename(self.filename)


   def saveas(self):
      '''Save the open document under a new name.'''
      if not self.isopen:
         return False

      name = self._querysavename()
      if name in (None, ''):
         return False
      self._savetofilename(name)
      return True


   def _savetofilename(self, name):
      '''Save the document to the specified name.'''
      assert name != ''
      file = open(name, 'w')
      fileio.save(self.doc, file)
      file.close()
      self.setclean()
      self.filename = name
      return True


   def open(self):
      '''Close the current document and open a new one.'''
      if not self.close():
         return False

      name = self._queryopenname()
      if name in (None, ''):
         return False

      file = open(name, 'rb')
      self.doc = boqdoc.Doc()
      fileio.load(file, self.doc)
      file.close()
      self.evt_opened()
      return True


